package com.pt25.base.util;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.format.TextStyle;
import java.time.temporal.WeekFields;
import java.util.Locale;

public class DateUtil {

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 时间戳转日期和时间字符串
     *
     * @param epochMilli 时间戳（毫秒）
     * @return 日期和时间字符串，格式为 "yyyy-MM-dd HH:mm:ss"
     */
    public static String timestampToDateTimeString(long epochMilli) {
        LocalDateTime dateTime = Instant.ofEpochMilli(epochMilli).atZone(ZoneId.systemDefault()).toLocalDateTime();
        return dateTime.format(DATE_TIME_FORMATTER);
    }

    /**
     * 时间戳转日期字符串
     *
     * @param epochMilli 时间戳（毫秒）
     * @return 日期字符串，格式为 "yyyy-MM-dd"
     */
    public static String timestampToDateString(long epochMilli) {
        LocalDateTime dateTime = Instant.ofEpochMilli(epochMilli).atZone(ZoneId.systemDefault()).toLocalDateTime();
        return dateTime.format(DATE_FORMATTER);
    }

    /**
     * 时间戳转时间字符串
     *
     * @param epochMilli 时间戳（毫秒）
     * @return 时间字符串，格式为 "HH:mm:ss"
     */
    public static String timestampToTimeString(long epochMilli) {
        LocalDateTime dateTime = Instant.ofEpochMilli(epochMilli).atZone(ZoneId.systemDefault()).toLocalDateTime();
        return dateTime.format(TIME_FORMATTER);
    }

    /**
     * 字符串日期转时间戳
     *
     * @param dateTimeString 日期和时间字符串，格式为 "yyyy-MM-dd HH:mm:ss"
     * @return 时间戳（毫秒）
     */
    public static long dateTimeStringToTimestamp(String dateTimeString) {
        try {
            LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, DATE_TIME_FORMATTER);
            return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("日期和时间格式不正确，应为：yyyy-MM-dd HH:mm:ss", e);
        }
    }

    /**
     * 字符串日期转时间戳
     *
     * @param dateString 日期字符串，格式为 "yyyy-MM-dd"
     * @return 时间戳（毫秒）
     */
    public static long dateStringToTimestamp(String dateString) {
        try {
            LocalDate date = LocalDate.parse(dateString, DATE_FORMATTER);
            return date.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("日期格式不正确，应为：yyyy-MM-dd", e);
        }
    }

    /**
     * 字符串时间转时间戳（当日时间）
     *
     * @param timeString 时间字符串，格式为 "HH:mm:ss"
     * @return 时间戳（毫秒）
     */
    public static long timeStringToTimestamp(String timeString) {
        try {
            LocalTime time = LocalTime.parse(timeString, TIME_FORMATTER);
            LocalDateTime dateTime = LocalDateTime.of(LocalDate.now(), time);
            return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("时间格式不正确，应为：HH:mm:ss", e);
        }
    }

    /**
     * 获取当前时间字符串
     *
     * @return 当前时间字符串
     */
    public static String getCurrentTimeString() {
        return LocalDateTime.now().format(DATE_TIME_FORMATTER);
    }

    /**
     * 获取当前时间戳
     *
     * @return 当前时间戳（毫秒）
     */
    public static long getCurrentTimestamp() {
        return Instant.now().toEpochMilli();
    }
    /**
     * 获取当前是第几周
     *
     * @return 当前是第几周
     */
    public static int getCurrentWeekOfYear() {
        LocalDate date = LocalDate.now();
        return date.get(WeekFields.of(Locale.getDefault()).weekOfYear());
    }

    /**
     * 获取当前是星期几
     *
     * @return 当前是星期几
     */
    public static String getCurrentDayOfWeek() {
        LocalDate date = LocalDate.now();
        return date.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault());
    }

    /**
     * 几天前是几号
     *
     * @param days 几天前
     * @return 日期字符串
     */
    public static String getDateDaysAgo(int days) {
        LocalDate date = LocalDate.now().minusDays(days);
        return date.format(DATE_FORMATTER);
    }

    /**
     * 几天后是几号
     *
     * @param days 几天后
     * @return 日期字符串
     */
    public static String getDateDaysAfter(int days) {
        LocalDate date = LocalDate.now().plusDays(days);
        return date.format(DATE_FORMATTER);
    }

    /**
     * 几天前是星期几
     *
     * @param days 几天前
     * @return 星期几字符串
     */
    public static String getDayOfWeekDaysAgo(int days) {
        LocalDate date = LocalDate.now().minusDays(days);
        return date.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault());
    }

    /**
     * 几天后是星期几
     *
     * @param days 几天后
     * @return 星期几字符串
     */
    public static String getDayOfWeekDaysAfter(int days) {
        LocalDate date = LocalDate.now().plusDays(days);
        return date.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault());
    }

    /**
     * 今天是什么节日（包括农历节日）
     *
     * @return 节日名称，如果没有则返回空字符串
     */
    public static String getTodayHoliday() {
        LocalDate date = LocalDate.now();
        return getHoliday(date);
    }

    /**
     * 判断给定日期是否是节日，并返回节日名称
     *
     * @param date 日期
     * @return 节日名称，如果没有则返回空字符串
     */
    private static String getHoliday(LocalDate date) {
        MonthDay monthDay = MonthDay.from(date);

        // 公历节日
        if (monthDay.equals(MonthDay.of(1, 1))) {
            return "元旦";
        } else if (monthDay.equals(MonthDay.of(5, 1))) {
            return "劳动节";
        } else if (monthDay.equals(MonthDay.of(10, 1))) {
            return "国庆节";
        }

        // 农历节日
        String lunarHoliday = getLunarHoliday(date);
        if (!lunarHoliday.isEmpty()) {
            return lunarHoliday;
        }

        return "";
    }

    /**
     * 判断给定日期是否是农历节日，并返回节日名称
     *
     * @param date 日期
     * @return 节日名称，如果没有则返回空字符串
     */
    private static String getLunarHoliday(LocalDate date) {
        // 使用库如 `chinese-lunar-java` 可以更准确地计算农历节日
        // 这个示例中仅简单返回空，实际使用中需要引入相关农历库进行实现
        // e.g., 农历正月初一 -> 春节
        // e.g., 农历八月十五 -> 中秋节
        return "";
    }
}